/*
 *
 *  Copyright (C) 2010 Tal Eisenberg
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fork.modbox;

import fork.Modbox;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import javax.swing.BorderFactory;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import tal.drivechain.chain.ChainNode.MSG;
import tal.drivechain.gui.GUIPopup;
import tal.drivechain.gui.TextButton;
import tal.drivechain.module.properties.ColorParser;
import tal.drivechain.module.xmlconfig.ModuleInfo;
import tal.drivechain.system.Globals;
import tal.drivechain.system.PluginLoader;

/**
 *
 * @author eisental
 */
public class NewPopup extends GUIPopup {
    Modbox owner;
    PackagesPanel packages = new PackagesPanel();
    ModulesPanel modules = new ModulesPanel();
    JTextField nameField = new JTextField(10);
    JLabel nameLabel = new JLabel("name:");
    JLabel titleLabel = new JLabel(" new node ");
    TextButton scriptButton, chooseFileButton, pasteButton;
    JTextField scriptField = new JTextField(10);
    JFileChooser chooser = new JFileChooser();

    public NewPopup(Modbox owner) {
        super(ColorParser.xor(owner.getColor()));

        Color xor = ColorParser.xor(owner.getColor());

        this.owner = owner;
        this.setLayout(new GridBagLayout());

        modules.init();
        packages.init();

        chooser.setCurrentDirectory(new File(Globals.getScriptsPath()));
        chooser.setDialogTitle("Choose Script");

        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0; c.gridy = 0; c.weightx = 1; c.fill = GridBagConstraints.BOTH; c.gridwidth = 3; c.anchor = GridBagConstraints.FIRST_LINE_START;
        this.add(titleLabel);

        c.gridx = 0; c.gridy = 1; c.weightx = 0; c.fill = GridBagConstraints.BOTH; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER;
        nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
        nameLabel.setOpaque(true);
        this.add(nameLabel, c);

        c.gridx = 1; c.gridy = 1; c.gridwidth = 3; c.weightx = 1.0; c.fill = GridBagConstraints.BOTH;
        this.add(nameField, c);

        c.gridx = 0; c.gridy = 2; c.weightx = 0; c.gridwidth = 1; c.fill = GridBagConstraints.BOTH;
        this.add(packages, c);

        c.gridx = 1; c.gridy = 2; c.weightx = 0; c.gridwidth = 3; c.fill = GridBagConstraints.BOTH;
        this.add(modules, c);

        c.gridx = 0; c.gridy = 3; c.weightx = 0; c.gridwidth = 1; c.fill = GridBagConstraints.BOTH;
        pasteButton = new TextButton("paste", xor, owner.getFont().deriveFont(Math.round(owner.getFont().getSize()-0.9)));
        pasteButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                NewPopup.this.setVisible(false);
                NewPopup.this.owner.sendShellCommand("paste");
            }
        });
        pasteButton.setToolTipText("Paste copied modules");
        pasteButton.setNegative(false);
        pasteButton.setMargin(new Insets(3,2,3,2));
        this.add(pasteButton, c);

        c.gridx = 1; c.gridy = 3; c.weightx = 0; c.gridwidth = 1; c.fill = GridBagConstraints.BOTH;
        scriptButton = new TextButton("  from file:  ", xor, this.owner.getFont().deriveFont(Math.round(owner.getFont().getSize()-0.9)));
        scriptButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                NewPopup.this.loadChain();
            }
        });
        scriptButton.setToolTipText("Load chain from a script file. Enter a script path in the text box and click to load.");
        scriptButton.setNegative(false);
        scriptButton.setMargin(new Insets(3,2,3,2));
        this.add(scriptButton, c);

        c.gridx = 2; c.gridy = 3; c.weightx = 1.0; c.gridwidth = 1; c.fill = GridBagConstraints.BOTH;
        c.ipadx = 0;
        scriptField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode()==KeyEvent.VK_ENTER)
                    loadChain();
            }
        });
        this.add(scriptField, c);

        c.gridx = 3; c.gridy = 3; c.weightx = 0; c.gridwidth = 1; c.fill = GridBagConstraints.BOTH;
        chooseFileButton = new TextButton("...", xor, this.owner.getFont().deriveFont(Math.round(owner.getFont().getSize()-0.9)));
        chooseFileButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                NewPopup.this.chooseFile();
            }
        });
        chooseFileButton.setToolTipText("Browse for script files.");
        chooseFileButton.setNegative(false);
        chooseFileButton.setMargin(new Insets(3,2,3,2));
        this.add(chooseFileButton, c);

        this.pack();
    }

    @Override
    public void setColor(Color c) {
        Color xor = ColorParser.xor(c);
        super.setColor(xor);

        titleLabel.setForeground(c);
        nameLabel.setBackground(ColorParser.lighterBy(xor, 0.2f));
        nameLabel.setForeground(xor);
        if (scriptButton!=null) scriptButton.setColor(xor);
        nameField.setForeground(Color.black);
        nameField.setBackground(xor);
        nameField.setCaretColor(xor.brighter());
        nameField.setSelectionColor(xor.darker());
        nameField.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));
        scriptField.setForeground(xor.brighter());
        scriptField.setBackground(Color.BLACK);
        scriptField.setCaretColor(xor.brighter().brighter());
        scriptField.setSelectionColor(xor.darker());
        scriptField.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));

        for (TextButton b : packages.buttons) {
            b.setColor(c);
        }
        packages.chainButton.setColor(xor);
        for (TextButton b : modules.buttons) {
            b.setColor(c);
        }
        modules.setBackground(ColorParser.lighterBy(xor, 0.2f));
        
    }

    @Override
    public void setFont(Font f) {
        super.setFont(f);
        titleLabel.setFont(f.deriveFont(Font.BOLD, (float)(f.getSize()*1.1*1.1)));
        nameField.setFont(f);
        nameLabel.setFont(f);
        scriptField.setFont(f);
        if (scriptButton!=null) scriptButton.setFont(f.deriveFont(Math.round(owner.getFont().getSize()-0.9)));
        for (TextButton b : packages.buttons) {
            b.setFont(f.deriveFont(Math.round(owner.getFont().getSize()-0.9)));
        }

        if (packages.chainButton!=null)
            packages.chainButton.setFont(f.deriveFont(Math.round(owner.getFont().getSize()-0.9)));
        for (TextButton b : modules.buttons)
            b.setFont(f.deriveFont(Math.round(owner.getFont().getSize()-0.9)));
        pack();
    }

    private void loadChain() {
        try {
            setVisible(false);
            owner.loadChain(nameField.getText(), scriptField.getText(), NewPopup.this.getLocation());
            nameField.setText("");
        } catch (IllegalArgumentException ie) {
            owner.log("While loading chain: " + ie.getMessage(), MSG.ERROR);
        }
    }

    private void chooseFile() {
        this.closeOnLostFocus = false;
        if (chooser.showDialog(this, "Choose")==JFileChooser.APPROVE_OPTION) {
            File f = chooser.getSelectedFile();
            if (f==null) owner.log("No file was selected.", MSG.WARNING);
            else {
                File scriptsPath = new File(Globals.getScriptsPath());
                File parent = f.getParentFile();
                String scriptText = "";
                while (true) {
                    if (parent==null) {
                        scriptText = f.getAbsolutePath();
                        break;
                    }  else if (parent.equals(scriptsPath)) {
                        scriptText = f.getAbsolutePath().substring(Globals.getScriptsPath().length());
                        break;
                    }
                    parent = parent.getParentFile();

                }
                scriptField.setText(scriptText);
            }
        }
        this.closeOnLostFocus = true;
    }

    class PackagesPanel extends JPanel {
        List<TextButton> buttons = new ArrayList<TextButton>();
        TextButton chainButton;

        public void init() {
            int packCount = PluginLoader.getPackageManagers().size();
            this.setLayout(new GridLayout(packCount+1, 1)); // for the chain button
            this.setBackground(Color.BLACK);
            Insets insets = new Insets(3, 2, 3, 2);
            for (final String name : PluginLoader.getPackageManagers().keySet()) {
                final TextButton b = new TextButton(name, NewPopup.this.owner.getColor(), owner.getFont().deriveFont(Math.round(owner.getFont().getSize()-0.9)));
                b.setToggleButton(true);
                b.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        NewPopup.this.modules.setPackage(name);
                        for (TextButton other : buttons) {
                            if (other!=b) {
                                other.setSelected(false);
                            }
                        }
                    }
                });
                if (name.equals(PluginLoader.getDefaultPackage().getPackageConfiguration().getPackageInfo().getName()))
                    b.setSelected(true);
                b.setMargin(insets);
                buttons.add(b);
                b.setToolTipText(PluginLoader.getPackageManagers().get(name).getPackageConfiguration().getPackageInfo().getDescription());
                this.add(b);
            }

            chainButton = new TextButton("Chain", ColorParser.xor(NewPopup.this.owner.getColor()), NewPopup.this.owner.getFont().deriveFont(Math.round(owner.getFont().getSize()-0.9)));
            chainButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    NewPopup.this.setVisible(false);
                    owner.createNewNode(nameField.getText(), "Chain", NewPopup.this.getLocation());
                    nameField.setText("");
                }
            });
            chainButton.setToolTipText("Create an empty chain node.");
            chainButton.setNegative(false);
            add(chainButton);
        }
    }

    class ModulesPanel extends JPanel {
        String currentPkg = "";
        List<TextButton> buttons = new ArrayList<TextButton>();

        public void init() {
            this.setBackground(Color.BLACK);
            setPackage(PluginLoader.getDefaultPackage().getPackageConfiguration().getPackageInfo().getName());
        }

        public void setPackage(String pkgName) {
            if (pkgName==null && currentPkg!=null) {
                clear();
                return;
            } if (pkgName.equals(currentPkg)) return;

            TreeMap<String, ModuleInfo> modules = PluginLoader.getAvailableModules(pkgName);

            this.setLayout(new GridLayout(PluginLoader.getPackageManagers().size()+1, 0));
            clear();

            Insets insets = new Insets(5, 3, 5, 3);

            for (final String modClass : modules.keySet()) {
                TextButton b = new TextButton(modClass, NewPopup.this.owner.getColor(), owner.getFont().deriveFont(Math.round(owner.getFont().getSize()-0.9)));
                b.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        NewPopup.this.setVisible(false);
                        owner.createNewNode(nameField.getText(), modClass, NewPopup.this.getLocation());
                        nameField.setText("");
                    }
                });
                b.setToolTipText(modules.get(modClass).getDescription());
                b.setMargin(insets);
                b.setNegative(false);
                this.add(b);
                buttons.add(b);
            }
            this.validate();
            NewPopup.this.pack();
            currentPkg = pkgName;
        }

        public void clear() {
            for (TextButton b : buttons)
                this.remove(b);
            buttons.clear();
            this.validate();
        }
    }

    @Override
    public void setVisible(boolean b) {
        super.setVisible(b);
        if (b) nameField.requestFocus();
    }
}
